﻿using UnityEngine;

public class BPInstruction_Implement
{
	virtual internal void DoStart(BPInstruction instruct)
	{
		
	}

	virtual internal bool DoUpdate(float deltaTime, BPInstruction instruct)
	{
		return true;
	}

	virtual internal void DoEnd(BPInstruction instruct) { }

	internal static BPInstruction_Implement Create(BPInstruction instruction)
	{
		switch (instruction.InstructType )
		{
			case BPInstruction.InstructionType.SendSceneEvent:
				return new BPI_SendSceneEvent();

			case BPInstruction.InstructionType.Create_Player:
				return new BPI_CreatePlayer();
			case BPInstruction.InstructionType.Create_Npc:
				return new BPI_CreateNpc();
			case BPInstruction.InstructionType.Create_EffectItem:
				return new BPI_CreateEffectItem();


			case BPInstruction.InstructionType.Wait:
				return new BPI_Wait();
			case BPInstruction.InstructionType.Kill_Trigger:
				return new BPI_KillTrigger();
			case BPInstruction.InstructionType.Kill_Instruction:
				return new BPI_KillInstruction();


			case BPInstruction.InstructionType.Open_Trigger:
				return new BPI_OpenTrigger();

			case BPInstruction.InstructionType.AttachAI:
				return new BPI_AddAI();
		}
		return null;
	}
}


public class BPI_CreatePlayer : BPInstruction_Implement
{

	internal override void DoStart(BPInstruction instruct)
	{
		Debug.Log("BPI_CreatePlayer start");
		//lastTime = 0;
		string playerKey = instruct.Params[0];
		//BattleLogic.Instance.CreatePlayer(playerKey, true);
		GamePlayFacade.Instance.Sub_Battle.CreatePlayer(playerKey, true);
	}

	float lastTime = 0;
	internal override bool DoUpdate(float deltaTime, BPInstruction instruct)
	{
		return true;
	}
}
public class BPI_CreateNpc : BPInstruction_Implement
{
	internal override void DoStart(BPInstruction instruct)
	{

		Debug.Log("BPI_CreateNPC start");
		string playerKey = instruct.Params[0];
		//BattleLogic.Instance.CreatePlayer(playerKey);
		GamePlayFacade.Instance.Sub_Battle.CreatePlayer(playerKey);
	}

	internal override bool DoUpdate(float deltaTime, BPInstruction instruct)
	{
		return true;
	}
}

public class BPI_CreateEffectItem : BPInstruction_Implement
{
	EffectItemFactory.EffectItemType type;
	float duration; 
	internal override void DoStart(BPInstruction instruct)
	{
		base.DoStart(instruct);
		type = (EffectItemFactory.EffectItemType)int.Parse(instruct.Params[0]);
		duration = int.Parse(instruct.Params[1]);
		lastTime = 0;
	}
	float lastTime;
	internal override bool DoUpdate(float deltaTime, BPInstruction instruct)
	{
		//if (BattleLogic.Instance.IsActive == false)
		if (GamePlayFacade.Instance.Sub_Battle.IsActive == false)
			return true;
		lastTime += deltaTime;
		if (lastTime > duration)
		{
			//var reusableObj =  BattleLogic.Instance.CreateEffectItem(type) as IInitByInstruction;
			var reusableObj = GamePlayFacade.Instance.Sub_Battle.CreateEffectItem(type) as IInitByInstruction;
			reusableObj.Init(instruct);
			lastTime = 0;
		}
		return false;
	}
}

public class BPI_AddAI : BPInstruction_Implement
{
	string tag;
	internal override void DoStart(BPInstruction instruct)
	{
		tag = instruct.Params[0];
		//RoleCtrl role = BattleLogic.Instance.GetRoleByTag(tag);
		RoleCtrl role = GamePlayFacade.Instance.Sub_Battle.GetRoleByTag(tag);
		if (null != role)
		{
			//TODO Need Be Replaced
			StateMachine ai = role.gameObject.GetComponent<StateMachine>();
			if(null == ai)
				ai = role.gameObject.AddComponent<StateMachine>();
			ai.StartMachine();
		}
	}
}

public class BPI_Wait : BPInstruction_Implement
{
	float waitTime = 0;
	internal override void DoStart(BPInstruction instruct)
	{
		Debug.Log("BPI_Wait Start");
		waitTime = float.Parse(instruct.Params[0]);
	}

	float lastTime = 0;
	internal override bool DoUpdate(float deltaTime, BPInstruction instruct)
	{
		lastTime += deltaTime;
		if (lastTime < waitTime)
		{
			Debug.Log("BPI_Wait Update");
			return false;
		}
		return true;
	}
}

public class BPI_KillInstruction : BPInstruction_Implement {

	int instructionIndex;
	internal override void DoStart(BPInstruction instruct)
	{
		instructionIndex = int.Parse(instruct.Params[0]);
		if (instructionIndex != -1)
		{
			BPInstruction opInstru = instruct.GetInstructionByIndex(instructionIndex);
			if (!opInstru.IsEnded)
				opInstru.DoEnd();
		}
		else
		{
			//BattleLogic.Instance.BattleProcess
		}
	}

	internal override bool DoUpdate(float deltaTime, BPInstruction instruct)
	{

		return true;
	}
	internal override void DoEnd(BPInstruction instruct)
	{

	}
}

public class BPI_KillTrigger : BPInstruction_Implement
{
	string triggerName;
	internal override void DoStart(BPInstruction instruct)
	{
		triggerName = instruct.Params[0];
		//BattleLogic.Instance.BattleProcess.DisableTrigger(triggerName);
		GamePlayFacade.Instance.Sub_Battle.BattleProcess.DisableTrigger(triggerName);
	}

	internal override bool DoUpdate(float deltaTime, BPInstruction instruct)
	{
		return true;
	}
	internal override void DoEnd(BPInstruction instruct)
	{
		
	}
}

public class BPI_OpenTrigger : BPInstruction_Implement
{
	string triggerName;
	internal override void DoStart(BPInstruction instruct)
	{
		triggerName = instruct.Params[0];
		//BattleLogic.Instance.BattleProcess.EnableTrigger(triggerName);
		GamePlayFacade.Instance.Sub_Battle.BattleProcess.EnableTrigger(triggerName);
	}

	internal override bool DoUpdate(float deltaTime, BPInstruction instruct)
	{
		return true;
	}
	internal override void DoEnd(BPInstruction instruct)
	{

	}
}

public class BPI_SendSceneEvent : BPInstruction_Implement
{
	int sceneEvent;
	int scene;
	internal override void DoStart(BPInstruction instruct)
	{
		sceneEvent = int.Parse(instruct.Params[0]);
		scene = int.Parse(instruct.Params[1]);
		//BattleLogic.Instance.ReceiveSceneEvent(sceneEvent, scene);
		//GamePlayFacade.Instance.Sub_Battle.ReceiveSceneEvent(sceneEvent, scene);
		//TODO  TO Brodcast Message
		GamePlayFacade.Instance.ReceiveSceneEvent(sceneEvent, scene);
	}

	internal override bool DoUpdate(float deltaTime, BPInstruction instruct)
	{
		return true;
	}

	internal override void DoEnd(BPInstruction instruct)
	{
		
	}
}